package com.kuaiditu.assistant.db;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.kuaiditu.assistant.api.ApiManager;
import com.kuaiditu.assistant.api.assistant_api.AssistantApi;
import com.kuaiditu.assistant.api.assistant_api.base.AssistantResponse;
import com.kuaiditu.assistant.api.kdy_api.STApi;
import com.kuaiditu.assistant.api.kdy_api.base.BaseSTResponse;
import com.kuaiditu.assistant.api.xz_api.XingZheApi;
import com.kuaiditu.assistant.api.xz_api.YTBaseResponse;
import com.kuaiditu.assistant.api.yd_api.YDApi;
import com.kuaiditu.assistant.api.yd_api.YDBaseResponse;
import com.kuaiditu.assistant.api.yd_api.entity.DaoSession;
import com.kuaiditu.assistant.api.zzt_api.ZZTApi;
import com.kuaiditu.assistant.api.zzt_api.base.BaseZTResponse;
import com.kuaiditu.assistant.entity.ExpressCom;
import com.kuaiditu.assistant.entity.Operator;

import java.io.IOException;
import java.util.List;

import io.reactivex.Observable;
import io.reactivex.ObservableSource;
import io.reactivex.android.schedulers.AndroidSchedulers;
import io.reactivex.annotations.NonNull;
import io.reactivex.functions.Consumer;
import io.reactivex.functions.Function;
import io.reactivex.schedulers.Schedulers;

/**
 * Created by Eenie on 2017/9/13.
 * Email: eeniework@gmail.com
 * Des:
 */

public class ExpressManager {

    private int task_id;
    private int express_code;
    private ExpressEntityDao mExpressEntityDao;
    private AssistantApi mAssistantApi;
    private XingZheApi mXingZheApi;
    private ZZTApi mZZTApi;
    private STApi mSTApi;
    private YDApi mYDApi;
    private Operator mOperator;

    private ExpressStateListener mExpressStateListener;

    public ExpressManager(int task_id, int express_code, ApiManager apiManager, DaoSession daoSession, Operator operator) {
        mExpressEntityDao = daoSession.getExpressEntityDao();
        mAssistantApi = apiManager.getAssistantApi();
        mXingZheApi = apiManager.getXingZheApi();
        mZZTApi = apiManager.getZZTApi();
        mSTApi = apiManager.getSTApi();
        mYDApi = apiManager.getYDApi();
        this.task_id = task_id;
        this.express_code = express_code;
        mOperator = operator;
    }


    public void setExpressStateListener(ExpressStateListener expressStateListener) {
        mExpressStateListener = expressStateListener;
    }

    public ObservableSource<AssistantResponse> addAcceptExpress(String express_num) {
        ExpressEntity expressEntity = loadExpress(express_num, ExpressEntity.EXPRESS_SEND_TYPE_ACCEPT);
        return sendTPOS(expressEntity);
    }


    public ObservableSource<AssistantResponse> addSignExpress(String express_num) {
        ExpressEntity expressEntity = loadExpress(express_num, ExpressEntity.EXPRESS_SEND_TYPE_ACCEPT);
        return signTPOS(expressEntity);
    }


    private void cacheExpress(ExpressEntity expressEntity) {
        mExpressEntityDao.insertOrReplace(expressEntity);
    }


    private ExpressEntity loadExpress(String express, int scan_type) {
        List<ExpressEntity> expressEntityList = mExpressEntityDao.queryBuilder()
                .where(ExpressEntityDao.Properties.Task_id.eq(task_id), ExpressEntityDao.Properties.Express_num.eq(express))
                .build().list();
        ExpressEntity expressEntity;
        if (expressEntityList.isEmpty()) {
            expressEntity = new ExpressEntity(task_id, express_code, express, scan_type);
            mExpressEntityDao.insertOrReplace(expressEntity);
            mExpressStateListener.onExpressAdd(expressEntity);
        } else {
            expressEntity = expressEntityList.get(0);
        }


        return expressEntity;
    }


    /**
     * 往第三方公司发送
     *
     * @param expressEntity
     * @return
     */
    private Observable<AssistantResponse> sendTPOS(ExpressEntity expressEntity) {
        switch (express_code) {
            case ExpressCom.EXPRESS_COM_CODE_YD:
                return sendYD(expressEntity);
            case ExpressCom.EXPRESS_COM_CODE_ZT:
                return sendZT(expressEntity);

            case ExpressCom.EXPRESS_COM_CODE_YT:
                return sendYT(expressEntity);

            case ExpressCom.EXPRESS_COM_CODE_ST:
                return sendST(expressEntity);
            default:
                return sendYD(expressEntity);
        }
    }

    private Observable<AssistantResponse> signTPOS(ExpressEntity expressEntity) {
        switch (express_code) {
            case ExpressCom.EXPRESS_COM_CODE_YD:
                return signYD(expressEntity);
            case ExpressCom.EXPRESS_COM_CODE_ZT:
                return signZT(expressEntity);

            case ExpressCom.EXPRESS_COM_CODE_YT:
                return signYT(expressEntity);
            case ExpressCom.EXPRESS_COM_CODE_ST:
                return signST(expressEntity);
            default:
                return signYD(expressEntity);
        }
    }


    private Observable<AssistantResponse> sendYT(final ExpressEntity expressEntity) {
        return mXingZheApi.addAcceptExpress(expressEntity.getExpress_num(), mOperator)
                .subscribeOn(Schedulers.io())
                .doOnNext(new Consumer<YTBaseResponse>() {
                    @Override
                    public void accept(YTBaseResponse response) throws Exception {
                        if (response.isSuccess()) {
                            sendTPOSSuccess(expressEntity);
                        } else {
                            sendTPOSFailure(expressEntity, response.getPrompt());
                        }
                        cacheExpress(expressEntity);
                    }
                })
                .flatMap(new Function<YTBaseResponse, ObservableSource<AssistantResponse>>() {
                    @Override
                    public ObservableSource<AssistantResponse> apply(@NonNull YTBaseResponse response) throws Exception {
                        return sendSelf(expressEntity);
                    }
                }).observeOn(AndroidSchedulers.mainThread());
    }

    private Observable<AssistantResponse> sendZT(final ExpressEntity expressEntity) {
        return mZZTApi.addAcceptExpress(expressEntity.getExpress_num(), mOperator)
                .subscribeOn(Schedulers.io())
                .doOnNext(new Consumer<BaseZTResponse>() {
                    @Override
                    public void accept(BaseZTResponse response) throws Exception {
                        JSONObject dataObj = JSON.parseArray(response.getResult()).getJSONObject(0);
                        if (dataObj.getBoolean("uploadResult")) {
                            sendTPOSSuccess(expressEntity);
                        } else {
                            sendTPOSFailure(expressEntity, "上传快递公司失败");
                           throw  new Exception(dataObj.getString("message"));
                        }
                        cacheExpress(expressEntity);
                    }
                })
                .flatMap(new Function<BaseZTResponse, ObservableSource<AssistantResponse>>() {
                    @Override
                    public ObservableSource<AssistantResponse> apply(@NonNull BaseZTResponse responseBody) throws Exception {
                        return sendSelf(expressEntity);
                    }
                }).observeOn(AndroidSchedulers.mainThread());
    }


    private Observable<AssistantResponse> sendST(final ExpressEntity expressEntity) {
        return mSTApi.addAcceptExpress(expressEntity.getExpress_num(), mOperator)
                .subscribeOn(Schedulers.io())
                .doOnNext(new Consumer<BaseSTResponse>() {
                    @Override
                    public void accept(BaseSTResponse response) throws Exception {
                        if (response.isSuccess()) {
                            if (response.getDataEnJson().getJSONObject("result").getString("success").contains(expressEntity.getExpress_num())) {
                                sendTPOSSuccess(expressEntity);
                            } else {
                                sendTPOSFailure(expressEntity, "上传快递公司失败");
                            }
                        } else {
                            sendTPOSFailure(expressEntity, response.getMsg());
                        }
                        cacheExpress(expressEntity);
                    }
                })
                .flatMap(new Function<BaseSTResponse, ObservableSource<AssistantResponse>>() {
                    @Override
                    public ObservableSource<AssistantResponse> apply(@NonNull BaseSTResponse response) throws Exception {
                        return sendSelf(expressEntity);
                    }
                }).observeOn(AndroidSchedulers.mainThread());
    }


    private Observable<AssistantResponse> sendYD(final ExpressEntity expressEntity) {
        return mYDApi.addAcceptExpress(expressEntity.getExpress_num(), mOperator)
                .subscribeOn(Schedulers.io())
                .doOnNext(new Consumer<YDBaseResponse>() {
                    @Override
                    public void accept(YDBaseResponse response) throws Exception {
                        JSONObject resObj = response.getDeEntity();
                        if (resObj.getJSONObject("dta").getString("st").equals("ok")) {
                            sendTPOSSuccess(expressEntity);
                        } else {
                            sendTPOSFailure(expressEntity, resObj.getJSONObject("dta").getString("ermsg"));
                        }
                        cacheExpress(expressEntity);
                    }
                })
                .flatMap(new Function<YDBaseResponse, ObservableSource<AssistantResponse>>() {
                    @Override
                    public ObservableSource<AssistantResponse> apply(@NonNull YDBaseResponse response) throws Exception {
                        return sendSelf(expressEntity);
                    }
                }).observeOn(AndroidSchedulers.mainThread());
    }


    private void sendTPOSSuccess(ExpressEntity expressEntity) {
        expressEntity.setState_code(ExpressEntity.EXPRESS_STATE_CODE_SEND_TPOS_SUCCESS);
        expressEntity.setState_des("上传快递公司成功");
    }

    private void sendSelfSuccess(ExpressEntity expressEntity) {
        expressEntity.setState_code(ExpressEntity.EXPRESS_STATE_CODE_SEND_SELF_SUCCESS);
        expressEntity.setState_des("上传成功");
    }

    private void sendTPOSFailure(ExpressEntity expressEntity, String msg) {
        expressEntity.setState_code(ExpressEntity.EXPRESS_STATE_CODE_SEND_TPOS_FAILURE);
        expressEntity.setState_des(msg);
    }


    private ObservableSource<AssistantResponse> sendSelf(final ExpressEntity expressEntity) {
        return mAssistantApi.addOrder(expressEntity, mOperator)
                .subscribeOn(Schedulers.io())
                .doOnNext(new Consumer<AssistantResponse>() {
                    @Override
                    public void accept(AssistantResponse assistantResponse) throws Exception {
                        sendSelfSuccess(expressEntity);
                        cacheExpress(expressEntity);
                    }
                });
    }




    private ObservableSource<AssistantResponse> signSelf(final ExpressEntity expressEntity) {
        return mAssistantApi.signOrder(expressEntity, mOperator)
                .subscribeOn(Schedulers.io());
    }






    private Observable<AssistantResponse> signZT(final ExpressEntity expressEntity) {
        return mZZTApi.addSignExpress(expressEntity.getExpress_num(), mOperator)
                .subscribeOn(Schedulers.io())
                .flatMap(new Function<BaseZTResponse, ObservableSource<AssistantResponse>>() {
                    @Override
                    public ObservableSource<AssistantResponse> apply(@NonNull BaseZTResponse response) throws Exception {
                        if (JSON.parseArray(response.getResult()).getJSONObject(0).getBoolean("uploadResult")) {
                            return signSelf(expressEntity);
                        } else {
                            throw new IOException("上传快递公司失败");
                        }
                    }
                }).observeOn(AndroidSchedulers.mainThread());
    }
    private Observable<AssistantResponse> signYD(final ExpressEntity expressEntity) {
        return mYDApi.addSignExpress(expressEntity.getExpress_num(), mOperator)
                .subscribeOn(Schedulers.io())
                .flatMap(new Function<YDBaseResponse, ObservableSource<AssistantResponse>>() {
                    @Override
                    public ObservableSource<AssistantResponse> apply(@NonNull YDBaseResponse response) throws Exception {
                        return signSelf(expressEntity);
                    }
                }).observeOn(AndroidSchedulers.mainThread());
    }
    private Observable<AssistantResponse> signYT(final ExpressEntity expressEntity) {


        return mXingZheApi.addSignExpress(expressEntity.getExpress_num(), mOperator)
                .subscribeOn(Schedulers.io())
                .flatMap(new Function<YTBaseResponse, ObservableSource<AssistantResponse>>() {
                    @Override
                    public ObservableSource<AssistantResponse> apply(@NonNull YTBaseResponse response) throws Exception {
                        return signSelf(expressEntity);
                    }
                }).observeOn(AndroidSchedulers.mainThread());
    }
    private Observable<AssistantResponse> signST(final ExpressEntity expressEntity) {
        return mSTApi.addSignExpress(expressEntity.getExpress_num(), mOperator)
                .subscribeOn(Schedulers.io())
                .flatMap(new Function<BaseSTResponse, ObservableSource<AssistantResponse>>() {
                    @Override
                    public ObservableSource<AssistantResponse> apply(@NonNull BaseSTResponse responseBody) throws Exception {
                        return signSelf(expressEntity);
                    }
                }).observeOn(AndroidSchedulers.mainThread());
    }


}
